package com.cbj.netty.proxy;



import com.cbj.netty.protocol.Content;
import com.cbj.netty.rpc.Dispatcher;
import com.cbj.netty.client.ClientFactory;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.CompletableFuture;

/**
 * @author Godc
 * @description
 */
public class MyProxy {


    public static <T>T proxyGet(Class<T> interfaceInfo){
        // 这里使用Jdk自带的动态代理,后续使用javassist提高反射效率，敬请期待
        // 获取动态代理必要的参数
        ClassLoader classLoader = interfaceInfo.getClassLoader();
        Class<?>[] methodInfo = {interfaceInfo};
        // 增强方法
        InvocationHandler invocationHandler = new InvocationHandler() {
            @Override
            public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
                Object res = null;
                Dispatcher dispatcher = Dispatcher.getDispatcher();
                Object o = dispatcher.get(interfaceInfo.getName());
                if(o == null){
                    // RPC调用
                    // 1.拿到调用服务，方法，参数 ==> 封装成Content
                    String name = interfaceInfo.getName();
                    String methodName = method.getName();
                    Class<?>[] parameterTypes = method.getParameterTypes();
                    Content content = new Content(name,methodName,parameterTypes,args);
                    // 1.1.Netty中数据发送都是基于ByteBuf，所以将content对象转换成字节数组
                    CompletableFuture<Object> transport = ClientFactory.transport(content,"rpc");
                    // 5.获得方法返回结果
                    res = transport.get();
                }else{
                    // local调用
                    Class<?> aClass = o.getClass();
                    try {
                        Method m = aClass.getMethod(method.getName(), method.getParameterTypes());
                        res = method.invoke(o, args);
                    } catch (NoSuchMethodException e) {
                        e.printStackTrace();
                    }catch (IllegalAccessException e){
                        e.printStackTrace();
                    }catch (InvocationTargetException e){
                        e.printStackTrace();
                    }
                }
                return res;

            }
        };
        return (T) Proxy.newProxyInstance(classLoader,methodInfo,invocationHandler);
    }
}
